#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <errno.h>
#include <signal.h>
#include <ctype.h>
#include <asm-generic/socket.h>
#include <sys/time.h>

#define LISTENMAX 4096
#define PTHREADMAX 12
#define MAXEVENTS 10000
#define BUFSIZE 1024
#define MAX_CLIENTS 20000
#define PROT 9000
#define MIN(x, y) ((x) < (y) ? (x) : (y))

// 任务结构体
typedef struct
{
    int fd;    // 客户端文件描述符
    char *buf; // 请求报文
    int len;   // 请求报文长度
} Task;

// 任务队列结构体
typedef struct
{
    Task *tasks;           // 任务数组（指针指向的一片空间）
    int capacity;          // 队列容量
    int size;              // 队列中任务的数量
    int front;             // 队列头指针
    int rear;              // 队列尾指针
    pthread_mutex_t mutex; // 互斥锁
    pthread_cond_t cond;   // 条件变量
    volatile int running;  // 是否运行
} ThreadSafeQueue;

// 线程池结构体
typedef struct
{
    pthread_t *threads;     // 线程数组（指针指向的一片空间）
    int thread_count;       // 线程池中的数量（初始化时为设置的最大线程数）
    ThreadSafeQueue *queue; // 任务队列
    volatile int running;   // 线程池是否运行
} ThreadPool;

// 客户端信息结构体
typedef struct
{
    int fd;                   // 客户端文件描述符
    char ip[INET_ADDRSTRLEN]; // 客户端IP地址
    int port;                 // 客户端端口号
    int ref_count;            // 引用计数
} ClientInfo;

// 客户端管理器结构体
typedef struct
{
    ClientInfo *infos;        // 客户端信息数组（指针指向的一片空间）
    pthread_mutex_t *mutexes; // 每个客户端信息对应一个互斥锁
    int capacity;             // 客户端信息数组容量
} ClientManager;

volatile int server_running = 1; // 服务器是否运行
int server_fd;                   // 服务器文件描述符
int epoll_fd;                    // epoll实例文件描述符
ThreadSafeQueue task_queue;      // 任务队列
ThreadPool thread_pool;          // 线程池
ClientManager client_manager;    // 客户端管理器

// 初始化线程池的任务队列
void init_queue(ThreadSafeQueue *queue, int capacity)
{
    queue->tasks = malloc(sizeof(Task) * capacity);
    queue->capacity = capacity;
    queue->size = 0;
    queue->front = 0;
    queue->rear = 0;
    queue->running = 1;
    pthread_mutex_init(&queue->mutex, NULL);
    pthread_cond_init(&queue->cond, NULL);
}

// 初始化线程池
void init_thread_pool(ThreadPool *pool, int thread_count, ThreadSafeQueue *queue)
{
    pool->threads = malloc(sizeof(pthread_t) * thread_count);
    pool->thread_count = thread_count;
    pool->queue = queue;
    pool->running = 1;
}

void *work_thread(void *arg);

// 启动线程池
void start_thread_pool(ThreadPool *pool)
{
    for (int i = 0; i < pool->thread_count; i++)
    {
        pthread_create(&pool->threads[i], NULL, work_thread, pool);
    }
}

// 初始化客户端管理器
void init_client_manager(ClientManager *manager, int capacity)
{
    manager->infos = calloc(capacity, sizeof(ClientInfo));
    manager->mutexes = malloc(sizeof(pthread_mutex_t) * capacity);
    manager->capacity = capacity;

    for (int i = 0; i < capacity; i++)
    {
        pthread_mutex_init(&manager->mutexes[i], NULL);
        manager->infos[i].fd = -1; // 初始化为-1，表示该位置没有客户端
    }
}

// 安全添加任务
int safe_add_task(ThreadSafeQueue *queue, Task task)
{
    pthread_mutex_lock(&queue->mutex);

    // 动态扩容（当前容量不足时）
    if (queue->size == queue->capacity)
    {
        int new_capacity = queue->capacity * 2;
        Task *new_tasks = realloc(queue->tasks, sizeof(Task) * new_capacity);
        if (!new_tasks)
        {
            pthread_mutex_unlock(&queue->mutex);
            return -1; // 扩容失败
        }
        queue->tasks = new_tasks;
        queue->capacity = new_capacity;
    }

    // 添加任务
    queue->tasks[queue->rear] = task;
    queue->rear = (queue->rear + 1) % queue->capacity;
    queue->size++;

    pthread_cond_signal(&queue->cond);
    pthread_mutex_unlock(&queue->mutex);
    return 0;
}

// 安全获取任务
int safe_get_task(ThreadSafeQueue *queue, Task *task)
{
    pthread_mutex_lock(&queue->mutex);
    while (queue->size == 0 && queue->running)
    {
        pthread_cond_wait(&queue->cond, &queue->mutex);
    }

    if (!queue->running)
    {
        pthread_mutex_unlock(&queue->mutex);
        return -1;
    }

    *task = queue->tasks[queue->front];
    queue->front = (queue->front + 1) % queue->capacity;
    queue->size--; // 待做任务数量减一

    pthread_mutex_unlock(&queue->mutex);
    return 0;
}

// 获取客户端信息
void init_client_info(ClientManager *manager, int fd, struct sockaddr_in *caddr)
{
    if (fd < 0 || fd >= manager->capacity)
        return;

    pthread_mutex_lock(&manager->mutexes[fd]);
    manager->infos[fd].fd = fd;
    strncpy(manager->infos[fd].ip, inet_ntoa(caddr->sin_addr), INET_ADDRSTRLEN);
    manager->infos[fd].port = ntohs(caddr->sin_port);
    manager->infos[fd].ref_count = 1;
    pthread_mutex_unlock(&manager->mutexes[fd]);
}

// 增加客户端引用计数
void client_ref_inc(ClientManager *manager, int fd)
{
    if (fd < 0 || fd >= manager->capacity)
        return;

    pthread_mutex_lock(&manager->mutexes[fd]);
    if (manager->infos[fd].fd == fd)
    {
        manager->infos[fd].ref_count++;
    }
    pthread_mutex_unlock(&manager->mutexes[fd]);
}

// 减少客户端引用计数
void client_ref_dec(ClientManager *manager, int fd)
{
    if (fd < 0 || fd >= manager->capacity)
        return;

    pthread_mutex_lock(&manager->mutexes[fd]);
    if (manager->infos[fd].fd == fd && --manager->infos[fd].ref_count <= 0)
    {
        close(fd);
        manager->infos[fd].fd = -1;
    }
    pthread_mutex_unlock(&manager->mutexes[fd]);
}

// 根据文件扩展名获取Content-Type
const char *get_content_type(const char *filename)
{
    const char *dot = strrchr(filename, '.');
    if (!dot)
        return "application/octet-stream";

    if (strcmp(dot, ".html") == 0 || strcmp(dot, ".htm") == 0)
        return "text/html";
    if (strcmp(dot, ".txt") == 0)
        return "text/plain";
    if (strcmp(dot, ".css") == 0)
        return "text/css";
    if (strcmp(dot, ".js") == 0)
        return "application/javascript";
    if (strcmp(dot, ".json") == 0)
        return "application/json";
    if (strcmp(dot, ".jpg") == 0 || strcmp(dot, ".jpeg") == 0)
        return "image/jpeg";
    if (strcmp(dot, ".png") == 0)
        return "image/png";
    if (strcmp(dot, ".gif") == 0)
        return "image/gif";
    if (strcmp(dot, ".ico") == 0)
        return "image/x-icon";
    if (strcmp(dot, ".pdf") == 0)
        return "application/pdf";
    if (strcmp(dot, ".zip") == 0)
        return "application/zip";

    return "application/octet-stream";
}

// 十六进制数字转数字
int hex_to_dec(char c)
{
    c = toupper(c);
    return (c >= 'A') ? (c - 'A' + 10) : (c - '0');
}

// URL解码函数
void url_decode(char *dst, const char *src)
{
    char a, b;
    while (*src)
    {
        if ((*src == '%') &&
            ((a = src[1]) && (b = src[2])) &&
            (isxdigit(a) && isxdigit(b)))
        {
            a = hex_to_dec(a);
            b = hex_to_dec(b);
            *dst++ = 16 * a + b;
            src += 3;
        }
        else
        {
            *dst++ = *src++;
        }
    }
    *dst++ = '\0';
}

// 解析HTTP请求
int parse_http_request(const char *request, char *filename, size_t max_len)
{
    const char *start = strchr(request, ' ');
    if (!start)
        return -1;

    start++;
    const char *end = strchr(start, ' ');
    if (!end)
        return -1;

    size_t len = end - start;
    if (len >= max_len)
        return -1;

    char encoded[256];
    memcpy(encoded, start, len);
    encoded[len] = '\0';

    url_decode(filename, encoded);

    if (strcmp(filename, "/") == 0)
    {
        strncpy(filename, "introduction.html", max_len);
        return 0;
    }

    if (filename[0] == '/')
    {
        memmove(filename, filename + 1, strlen(filename));
    }

    return 0;
}

// 工作线程函数
void *work_thread(void *arg)
{
    ThreadPool *pool = (ThreadPool *)arg;

    while (pool->running) // 线程池运行标志
    {
        // 1. 从任务队列中获取任务
        Task task;
        if (safe_get_task(pool->queue, &task) != 0)
        {
            continue;
        }

        // 2. 处理任务（请求报文）
        char filename[256] = {0};
        if (parse_http_request(task.buf, filename, sizeof(filename)) != 0)
        {
            const char *bad_request =
                "HTTP/1.1 400 Bad Request\r\n"
                "Content-Type: text/plain\r\n"
                "Content-Length: 15\r\n"
                "Connection: close\r\n\r\n"
                "Bad Request";
            write(task.fd, bad_request, strlen(bad_request));
            client_ref_dec(&client_manager, task.fd);
            free(task.buf);
            continue;
        }

        char fullpath[1024] = {0};
        snprintf(fullpath, sizeof(fullpath), "%s", filename);

        int file_fd = open(fullpath, O_RDONLY);
        if (file_fd == -1)
        {
            const char *not_found =
                "HTTP/1.1 404 Not Found\r\n"
                "Content-Type: text/plain\r\n"
                "Content-Length: 13\r\n"
                "Connection: close\r\n\r\n"
                "File not found";
            write(task.fd, not_found, strlen(not_found));
            client_ref_dec(&client_manager, task.fd);
            free(task.buf);
            continue;
        }

        struct stat file_stat;
        if (fstat(file_fd, &file_stat) == -1)
        {
            close(file_fd);
            client_ref_dec(&client_manager, task.fd);
            free(task.buf);
            continue;
        }

        const char *content_type = get_content_type(filename);

        char response_header[1024];
        int header_len = snprintf(response_header, sizeof(response_header),
                                  "HTTP/1.1 200 OK\r\n"
                                  "Content-Type: %s\r\n"
                                  "Content-Length: %ld\r\n"
                                  "Connection: close\r\n\r\n",
                                  content_type, file_stat.st_size);

        // 3. 发送响应报文
        ssize_t sent = write(task.fd, response_header, header_len);
        if (sent != header_len)
        {
            close(file_fd);
            client_ref_dec(&client_manager, task.fd);
            free(task.buf);
            continue;
        }

        // 设置非阻塞模式
        fcntl(task.fd, F_SETFL, O_NONBLOCK);

        off_t offset = 0;
        size_t remaining = file_stat.st_size;

        while (remaining > 0)
        {
            ssize_t bytes_sent = sendfile(task.fd, file_fd, &offset, remaining);
            if (bytes_sent == -1)
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                {
                    usleep(1000); // 短暂等待后重试
                    continue;
                }
                break; // 其他错误直接退出
            }
            remaining -= bytes_sent;
        }

        // 4. 关闭文件描述符和减少引用计数
        close(file_fd);
        client_ref_dec(&client_manager, task.fd);
        free(task.buf);
    }
    return NULL;
}

void log_connection(const char *ip, int port, const char *status)
{
    FILE *log_file = fopen("/var/log/httpserver.log", "a");
    if (log_file)
    {
        time_t now = time(NULL);
        char *time_str = ctime(&now);
        time_str[strlen(time_str) - 1] = '\0'; // 移除换行符
        fprintf(log_file, "[%s] [%s] %s:%d\n", time_str, status, ip, port);
        fclose(log_file);
    }
}

// 记录请求日志
void log_request(const char *ip, int port, const char *filename)
{
    FILE *log_file = fopen("/var/log/httpserver.log", "a");
    if (log_file)
    {
        time_t now = time(NULL);
        char *time_str = ctime(&now);
        time_str[strlen(time_str) - 1] = '\0'; // 移除换行符
        fprintf(log_file, "[%s] [REQUEST] %s:%d - %s\n", time_str, ip, port, filename);
        fclose(log_file);
    }
}

// 记录错误日志
void log_error(const char *error_msg)
{
    FILE *log_file = fopen("/var/log/httpserver.log", "a");
    if (log_file)
    {
        time_t now = time(NULL);
        char *time_str = ctime(&now);
        time_str[strlen(time_str) - 1] = '\0'; // 移除换行符
        fprintf(log_file, "[%s] [ERROR] %s\n", time_str, error_msg);
        fclose(log_file);
    }
}

// 处理客户端连接
void handle_client_connection(int epoll_fd, int server_fd)
{
    struct sockaddr_in caddr;
    socklen_t c_len = sizeof(caddr);
    int c_fd = accept(server_fd, (struct sockaddr *)&caddr, &c_len);
    if (c_fd == -1)
        return;

    // 设置超时（5秒）
    struct timeval timeout = {.tv_sec = 5, .tv_usec = 0};
    setsockopt(c_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
    setsockopt(c_fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));

    // 记录新连接
    log_connection(inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port), "CONNECTED");

    fcntl(c_fd, F_SETFL, O_NONBLOCK);
    init_client_info(&client_manager, c_fd, &caddr);

    struct epoll_event ev;
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = c_fd;
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, c_fd, &ev) == -1)
    {
        log_error("epoll_ctl failed"); // 添加错误日志
        perror("添加客户端到epoll失败");
        client_ref_dec(&client_manager, c_fd); // 确保清理客户端管理器中的信息
        close(c_fd);
        log_error("Failed to add client to epoll"); // 记录错误日志
        return;
    }
}

// 处理客户端数据
void handle_client_data(int epoll_fd, int fd)
{
    char buf[BUFSIZE];
    ssize_t n;
    int total_read = 0;

    // 边缘触发必须循环读取到 EAGAIN
    while (1)
    {
        n = read(fd, buf + total_read, sizeof(buf) - total_read);
        if (n == -1)
        {
            if (errno == EAGAIN || errno == EWOULDBLOCK)
            {
                break; // 数据已读完
            }
            else
            {
                perror("read error");
                goto close_conn; // 真正出错，关闭连接
            }
        }
        else if (n == 0)
        {
            goto close_conn; // 客户端关闭连接
        }
        total_read += n;
    }

    // 处理有效数据（total_read > 0）
    if (total_read > 0)
    {
        char *task_buf = malloc(total_read);
        memcpy(task_buf, buf, total_read);
        Task task = {.fd = fd, .buf = task_buf, .len = total_read};
        client_ref_inc(&client_manager, fd);
        if (safe_add_task(&task_queue, task) != 0)
        {
            free(task_buf);
            client_ref_dec(&client_manager, fd);
        }
        return; // 成功提交任务后返回
    }

close_conn:
    log_connection(client_manager.infos[fd].ip,
                   client_manager.infos[fd].port, "DISCONNECTED");
    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, NULL);
    client_ref_dec(&client_manager, fd);
}

// 优雅关闭
void graceful_shutdown(int sig)
{
    server_running = 0;

    // 删除PID文件
    unlink("/var/run/httpserver.pid");

    // 关闭监听socket以停止接受新连接
    close(server_fd);

    // 停止线程池
    pthread_mutex_lock(&task_queue.mutex);
    task_queue.running = 0;
    pthread_cond_broadcast(&task_queue.cond);
    pthread_mutex_unlock(&task_queue.mutex);

    // 等待线程退出
    for (int i = 0; i < thread_pool.thread_count; i++)
    {
        pthread_join(thread_pool.threads[i], NULL);
    }

    // 关闭所有客户端连接
    for (int i = 0; i < client_manager.capacity; i++)
    {
        if (client_manager.infos[i].fd != -1)
        {
            close(client_manager.infos[i].fd);
        }
    }

    // 释放资源
    free(task_queue.tasks);
    free(client_manager.infos);
    free(client_manager.mutexes);
    free(thread_pool.threads);

    exit(EXIT_SUCCESS);
}

void daemonize(int keep_fd)
{
    pid_t pid;

    /* 第一次fork：脱离终端 */
    pid = fork();
    if (pid < 0)
    {
        perror("fork failed");
        exit(EXIT_FAILURE);
    }
    if (pid > 0) // 父进程退出
    {
        exit(EXIT_SUCCESS);
    }

    /* 创建新会话，成为进程组组长 */
    if (setsid() < 0)
    {
        perror("setsid failed");
        exit(EXIT_FAILURE);
    }

    /* 忽略终端信号 */
    signal(SIGCHLD, SIG_IGN); // 忽略子进程退出信号
    signal(SIGHUP, SIG_IGN);  // 忽略终端挂断信号

    /* 第二次fork：确保不会获得控制终端 */
    pid = fork();
    if (pid < 0)
    {
        perror("fork failed");
        exit(EXIT_FAILURE);
    }
    if (pid > 0) // 父进程退出
    {
        exit(EXIT_SUCCESS);
    }

    /* 设置工作目录 */
    chdir("/root/http"); // 切换到web根目录

    /* 清除文件创建掩码 */
    umask(0); // 允许创建的文件具有最大权限

    /* 关闭所有不需要的文件描述符 */
    // 关闭所有打开的文件描述符
    int x;
    for (x = sysconf(_SC_OPEN_MAX); x >= 0; x--)
    {
        close(x);
    }

    /* 重定向标准输入输出到/dev/null */
    int fd = open("/dev/null", O_RDWR);
    dup(fd); // stdout
    dup(fd); // stderr
}

// 写入pid文件
void write_pid_file()
{
    FILE *f = fopen("/var/run/httpserver.pid", "w");
    if (f)
    {
        fprintf(f, "%d\n", getpid());
        fclose(f);
        chmod("/var/run/httpserver.pid", 0644); // 设置权限
    }
}

// 统一的错误检查函数
void check_error(int condition, const char *error_msg, int should_close_server)
{
    if (condition)
    {
        log_error(error_msg); // 添加错误日志记录
        perror(error_msg);
        if (should_close_server)
        {
            if (server_fd != -1)
                close(server_fd);
            if (epoll_fd != -1)
                close(epoll_fd);
            // 释放其他资源
            if (task_queue.tasks)
                free(task_queue.tasks);
            if (client_manager.infos)
                free(client_manager.infos);
            if (client_manager.mutexes)
                free(client_manager.mutexes);
            if (thread_pool.threads)
                free(thread_pool.threads);
        }
        exit(EXIT_FAILURE);
    }
}